﻿using DataModels.Dto;
using DataModels.Entities.Base;
using DataModels.Entities.Feedback;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Protocol;
using MQTTnet.Server;
using Services.Feedback;
using Services.Visitor;
using System.Drawing;
using System.Formats.Asn1;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using static Dm.net.buffer.ByteArrayBuffer;

namespace PropertyManagementWebApi.Controllers
{
    public class AccessControlController(FeedbackService feedBacksService) : BaseController
    {
        protected readonly FeedbackService _feedBacksService = feedBacksService;

        /// <summary>
        /// 获取当前人门禁列表
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public ResponseModel GetAccessControlList(OpenDoorRequest o) {
            return _feedBacksService.GetAccessControlList(o);
        }

        /// <summary>
        /// 扫码开门
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResponseModel> ScanCodeOpenDoor(OpenDoorRequest o)
        {
            ResponseModel rm2 = _feedBacksService.GetAccessControlList(o);
            if (rm2.Data != null)
            {
                List<AccessControl> acs = (List<AccessControl>)rm2.Data;
                AccessControl? a1=acs.Where(a=>a.Id== o.saomaid).FirstOrDefault();
                if (a1 != null)
                    return await OpenDoor(o.saomaid);
            }
            rm2.SetError("无开门权限");
            return rm2;
        }

        // 信号量：用于让OpenDoor方法等待消息接收
        private static readonly ManualResetEventSlim _messageReceivedEvent = new ManualResetEventSlim(false);
        /// <summary>
        /// MQTT方式开门
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResponseModel> OpenDoor(int acid)
        {
            OpenDoorRequest openDoorRequest = new OpenDoorRequest();
            openDoorRequest.ACid = acid;
            ResponseModel rm2 = _feedBacksService.GetAccessControlList(openDoorRequest);
            if (rm2.Data != null)
            {
                AccessControl acs = (AccessControl)rm2.Data;

                var options = new MqttClientOptionsBuilder()
                            .WithClientId(Guid.NewGuid().ToString().Replace("-", "").ToUpper())
                            .WithTcpServer("127.0.0.1", 7003)
                            //.WithTcpServer("119.36.93.100", 7003)
                            ;

                // 添加认证信息（若有）
                //if (!string.IsNullOrEmpty(username))
                //{
                //    options.WithCredentials(username, password);
                //}
                var factory = new MqttFactory();
                var _mqttClient = factory.CreateMqttClient();
                try
                {
                    await _mqttClient.ConnectAsync(options.Build());
                }
                catch (Exception)
                {
                    Console.WriteLine($"  MQTT连接失败");
                    rm2.SetError("开门错误");
                    return rm2;
                }
                if (!_mqttClient.IsConnected)
                {
                    Console.WriteLine($"  MQTT连接失败");
                    rm2.SetError("开门错误");
                    return rm2;
                }

                // 订阅主题
                await SubscribeAsync(acs.CtoS_topic, _mqttClient);
                // 2. 绑定消息接收事件（处理收到的消息）
                _mqttClient.ApplicationMessageReceivedAsync += async e =>
                {
                    // 解析收到的消息
                    var receivedTopic = e.ApplicationMessage.Topic;
                    var messagePayload = Encoding.UTF8.GetString(e.ApplicationMessage.PayloadSegment);

                    Console.WriteLine($"收到消息 - 主题: {receivedTopic}, 内容: {messagePayload}");

                    // 触发信号量，通知Main方法可以继续执行
                    _messageReceivedEvent.Set();

                    // 若需要异步处理，可添加 await 操作
                    await Task.CompletedTask;
                };

                // 发布消息
                var sendopen =new
                {
                    cmd = 1,  //1 远程开门命令
                    cmd_reply = 1, //0 不需要应答，1需要应答
                    cmd_reply_id = 1, //返回提交的cmd_reply_id
                    status = 0,  //0 开门
                    select = 1  // 1 第一路继电器 2第二路继电器 3 两路继电器同开
                };
                var message = new MqttApplicationMessage
                {
                    Topic = acs.StoC_topic,
                    Payload = Encoding.Default.GetBytes(JsonSerializer.Serialize(sendopen)),
                    QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce
                    //Retain = true  // 服务端是否保留消息。true为保留，如果有新的订阅者连接，就会立马收到该消息。
                };
                await _mqttClient.PublishAsync(message);

                // Main方法等待：直到收到消息或超时（30秒）
                bool isReceived = _messageReceivedEvent.Wait(TimeSpan.FromSeconds(30));

                // 断开连接
                await _mqttClient.DisconnectAsync();
                _messageReceivedEvent.Reset();
                if (isReceived)
                {
                    rm2.Success("开门成功");
                    return rm2;
                }
                else
                {
                    rm2.SetError("开门失败,门禁未响应");
                    return rm2;
                }              
                
            }
            rm2.SetError("开门失败,未找到门禁");
            return rm2;

        }
        // 订阅主题
        async Task SubscribeAsync(string topic, IMqttClient _mqttClient)
        {
            if (!_mqttClient.IsConnected)
            {
                Console.WriteLine("未连接，无法订阅主题");
                return;
            }

            var subscribeOptions = new MqttClientSubscribeOptionsBuilder()
                .WithTopicFilter(f => f.WithTopic(topic))
                .Build();

            var subscribeResult = await _mqttClient.SubscribeAsync(subscribeOptions);
            
        }
    }
}
